package gr.aueb.cs.mscis.chordroid.chord;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.io.StreamCorruptedException;
import java.net.Socket;

/**
 * This class undertakes the procedure of sending {@code RemoteMessage}s
 * to another {@code Node}'s {@code RemoteMessageDaemon} 
 * @author lupin
 *
 */
public class RemoteMessageAgent implements Runnable, Serializable{

	private static final long serialVersionUID = 1L;
	private NodeIdentifier receiver;	
	private RemoteMessage remoteMessage;

	public RemoteMessageAgent() { }

	public void run() {
	}

	/**
	 * Sends a {@RemoteMessage} asynchronously
	 * @param remoteMessage
	 * @param receiver
	 */
	public static synchronized void sendRemoteMessage(RemoteMessage remoteMessage, NodeIdentifier receiver) {
		try {
			Socket toServer = new Socket(receiver.getAddr(), receiver.getPort());

			ObjectOutputStream out = new ObjectOutputStream(toServer.getOutputStream());
			out.writeObject(remoteMessage);
			
			toServer.close();
		}catch (IOException e) {
			e.printStackTrace();
		} 
	}
	
	/**
	 * Sends a synchronous {@code RemoteMessage}
	 * @param remoteMessage
	 * @param receiver
	 * @return
	 */
	public static RemoteMessage sendSynchronousRemoteMessage(RemoteMessage remoteMessage, NodeIdentifier receiver) {
		try {
			Socket toServer = new Socket(receiver.getAddr(), receiver.getPort());
			
			ObjectOutputStream out = new ObjectOutputStream(toServer.getOutputStream());
			out.writeObject(remoteMessage);
			
			ObjectInputStream in = new ObjectInputStream(toServer.getInputStream());
			RemoteMessage msg = (RemoteMessage) in.readObject();
			
			toServer.close();
			return msg;
			
		} catch (EOFException eofe) {
			// it's produced when waiting for a response from a node that's shutting down
			return null;
		} catch (StreamCorruptedException sce) {
			// it's produced when waiting for a response from a node that's shutting down
			return null;
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
			return null;
	}

	public void setReceiver(NodeIdentifier node) {
		this.receiver = node;
	}

	public NodeIdentifier getReceiver() {
		return receiver;
	}

	public void setRemoteMessage(RemoteMessage remoteMessage) {
		this.remoteMessage = remoteMessage;
	}

	public RemoteMessage getRemoteMessage() {
		return remoteMessage;
	}

}